using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Resources;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

using AMPLibrary.Collections;
using AMPLibrary.Controllers;

namespace AMPLibrary.Media
{
    [Serializable]
    public class MediaFile : ISerializable
    {
        /// <summary>
        /// Property, get/set the path to the file
        /// </summary>
        public string Path
        {
            get;
            set;
        }

        /// <summary>
        /// Property, get/set the path to the file
        /// </summary>
        public string MimeType
        {
            get;
            set;
        }

        /// <summary>
        /// 
        /// </summary>
        public TimeSpan Duration
        {
            get;
            set;
        }

        /// <summary>
        /// 
        /// </summary>
        public int PlayCount
        {
            get;
            private set;
        }

        /// <summary>
        /// 
        /// </summary>
        public int SkipCount
        {
            get;
            private set;
        }

        /// <summary>
        /// 
        /// </summary>
        public DateTime DateAdded
        {
            get;
            private set;
        }

        /// <summary>
        /// 
        /// </summary>
        public UserMediaRating UserMediaRating
        {
            get;
            set;
        }

        /// <summary>
        /// 
        /// </summary>
        public bool IsFavorited
        {
            get;
            set;
        }

        /// <summary>
        /// 
        /// </summary>
        public DateTime LastPlayed
        {
            get;
            private set;
        }

        /// <summary>
        /// 
        /// </summary>
        public Tag Tag
        {
            get;
            set;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        /// <param name="dateAdded"></param>
        /// <returns></returns>
        public static MediaFile LoadMedia(string path, DateTime dateAdded)
        {
            MediaFile loadedMedia = LoadMedia(path);
            loadedMedia.DateAdded = dateAdded;

            return loadedMedia;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static MediaFile LoadMedia(string path)
        {
            MediaFile media = new MediaFile();

            string mimeType = MediaTypes.GetMimeType(path);

            TagLib.File file = null;

            try
            {
                file = TagLib.File.Create(path);
            }
            catch
            {
                file = null;
            }

            switch (mimeType)
            {
                case MimeTypes.AVI:
                    {
                        try
                        {
                            VideoCollection videoCollection = VideoCollection.GetVideoCollection();
                            return (from m in videoCollection where m.Path == path select m).Single();
                        }
                        catch
                        {
                        }

                        if (file != null)
                        {
                            media.Tag = new Tag(file, path);
                            media.Duration = file.Properties.Duration;
                        }
                        else
                        {
                            media.Tag = new Tag();
                            media.Duration = new TimeSpan();
                        }

                        media.LastPlayed = DateTime.MinValue;
                        media.Path = path;
                        media.MimeType = MimeTypes.AVI;
                        media.PlayCount = 0;
                        media.UserMediaRating = UserMediaRating.Unrated;
                        break;
                    }

                case MimeTypes.MP3:
                    {
                        try
                        {
                            MusicCollection musicCollection = MusicCollection.GetMusicCollection();
                            return (from m in musicCollection where m.Path == path select m).Single();
                        }
                        catch
                        {
                        }

                        if (file != null)
                        {
                            media.Tag = new Tag(file, path);
                            media.Duration = file.Properties.Duration;
                        }
                        else
                        {
                            media.Tag = new Tag();
                            media.Duration = new TimeSpan();
                        }

                        media.LastPlayed = DateTime.MinValue;
                        media.Path = path;
                        media.MimeType = MimeTypes.MP3;
                        media.PlayCount = 0;
                        media.UserMediaRating = UserMediaRating.Unrated;
                        break;
                    }
                default:
                    {
                        media.Tag = new Tag();
                        media.Duration = new TimeSpan();
                        media.LastPlayed = DateTime.MinValue;
                        media.Path = path;
                        media.MimeType = string.Empty;
                        media.PlayCount = 0;
                        media.UserMediaRating = UserMediaRating.Unrated;
                        break;
                    }
            }

            return media;
        }

        /// <summary>
        /// Constructor, default, 
        /// </summary>
        public MediaFile()
        {
            this.Tag = new Tag();
            this.Duration = new TimeSpan();
            this.Path = string.Empty;
            this.MimeType = string.Empty;
            this.PlayCount = 0;
            this.SkipCount = 0;
            this.UserMediaRating = UserMediaRating.Unrated;
            this.LastPlayed = DateTime.MinValue;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="media"></param>
        public void IncrimentPlayCount()
        {
            WatchFolderController wfc = WatchFolderController.GetWatchFolderController();
            wfc.PauseMusic = true;

            System.Threading.Thread.Sleep(100);

            MediaFile foundMedia = LoadMedia(this.Path);
            foundMedia.PlayCount++;

            wfc.PauseVideo = false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="media"></param>
        public void DeIncrimentPlayCount()
        {
            WatchFolderController wfc = WatchFolderController.GetWatchFolderController();
            wfc.PauseMusic = true;

            System.Threading.Thread.Sleep(100);

            MediaFile foundMedia = LoadMedia(this.Path);
            foundMedia.PlayCount--;

            if (foundMedia.PlayCount < 0)
                foundMedia.PlayCount = 0;

            wfc.PauseVideo = false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="media"></param>
        public void SetLastPlayed()
        {
            WatchFolderController wfc = WatchFolderController.GetWatchFolderController();
            wfc.PauseMusic = true;
            wfc.PauseVideo = true;

            System.Threading.Thread.Sleep(100);

            MediaFile foundMedia = LoadMedia(this.Path);
            foundMedia.LastPlayed = DateTime.Now;

            wfc.PauseMusic = false;
            wfc.PauseVideo = false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="media"></param>
        public void SetLastPlayed(UserMediaRating userMediaRating)
        {
            WatchFolderController wfc = WatchFolderController.GetWatchFolderController();
            wfc.PauseMusic = true;
            wfc.PauseVideo = true;

            System.Threading.Thread.Sleep(100);

            MediaFile foundMedia = LoadMedia(this.Path);
            foundMedia.UserMediaRating = userMediaRating;

            wfc.PauseMusic = false;
            wfc.PauseVideo = false;
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="info"></param>
        /// <param name="ctxt"></param>
        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Tag", this.Tag);
            info.AddValue("Path", this.Path);
            info.AddValue("MimeType", this.MimeType);
            info.AddValue("Duration", this.Duration);
            info.AddValue("DateAdded", this.DateAdded);
            info.AddValue("UserMediaRating", this.UserMediaRating);
            info.AddValue("PlayCount", this.PlayCount);
            info.AddValue("SkipCount", this.SkipCount);
            info.AddValue("IsFavorited", this.IsFavorited);
            info.AddValue("LastPlayed", this.LastPlayed);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="info"></param>
        /// <param name="ctxt"></param>
        public MediaFile(SerializationInfo info, StreamingContext ctxt)
        {
            this.Tag = new Tag();
            this.Duration = new TimeSpan();
            this.Path = string.Empty;
            this.MimeType = string.Empty;
            this.PlayCount = 0;
            this.SkipCount = 0;
            this.UserMediaRating = UserMediaRating.Unrated;
            this.LastPlayed = DateTime.MinValue;

            this.Tag = (Tag)info.GetValue("Tag", typeof(Tag));
            this.Path = (string)info.GetValue("Path", typeof(string));
            this.MimeType = (string)info.GetValue("MimeType", typeof(string));
            this.Duration = (TimeSpan)info.GetValue("Duration", typeof(TimeSpan));
            this.DateAdded = (DateTime)info.GetValue("DateAdded", typeof(DateTime));
            this.UserMediaRating = (UserMediaRating)info.GetValue("UserMediaRating", typeof(UserMediaRating));
            this.PlayCount = (int)info.GetValue("PlayCount", typeof(int));
            this.SkipCount = (int)info.GetValue("SkipCount", typeof(int));
            this.IsFavorited = (bool)info.GetValue("IsFavorited", typeof(bool));
            this.LastPlayed = (DateTime)info.GetValue("LastPlayed", typeof(DateTime));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool Exists()
        {
            return File.Exists(this.Path);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        private TimeSpan GetDuration(string path)
        {
            TagLib.File file = TagLib.File.Create(path);

            if (file == null)
                return new TimeSpan();

            if (file.Properties.Duration == null)
                return new TimeSpan();

            return file.Properties.Duration;
        }
    }
}
